package com.gitee.wsl.serialization.time

import kotlin.time.Instant
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlin.time.ExperimentalTime

@OptIn(ExperimentalTime::class)
typealias TimestampSerializer = @Serializable(with = InstantTimestampSerializer::class) Instant?

@OptIn(ExperimentalTime::class)
object InstantTimestampSerializer : KSerializer<Instant?> {
    @Serializable
    private data class Boxed(
        val seconds: Long = 0L,
        val nanos: Int = 0
    )

    override val descriptor: SerialDescriptor = Boxed.serializer().descriptor

    @OptIn(ExperimentalSerializationApi::class)
    override fun serialize(encoder: Encoder, value: Instant?) {
        encoder.encodeNullableSerializableValue(
            Boxed.serializer(),
            value?.let {
                Boxed(
                    seconds = it.epochSeconds,
                    nanos = it.nanosecondsOfSecond
                )
            }
        )
    }

    @OptIn(ExperimentalSerializationApi::class)
    override fun deserialize(decoder: Decoder): Instant? {
        return decoder.decodeNullableSerializableValue(Boxed.serializer())?.let {
            Instant.fromEpochSeconds(it.seconds, it.nanos)
        }
    }
}